import datetime
import random
from threading import current_thread

from django.contrib.auth import authenticate, login, logout
from django.db import transaction
from django.shortcuts import redirect
from django_redis import get_redis_connection
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

from saas_main import models
from saas_main.serializer.account_serializer import UserSerializer, MobileSerializer, LoginSerializer, \
    UserRightSerializer, PaymentSerializer
from utils.alipay import AliPay
from utils.encrypt import uid
from django.conf import settings


class RegisterApiView(APIView):
    def post(self, request):
        serializer = UserSerializer(data=request.data)
        if serializer.is_valid():
            try:
                with transaction.atomic():
                    user_obj = serializer.save()
                    right_obj = models.UserRightConfig.objects.filter(title='免费版').first()
                    right_ser = UserRightSerializer(data={"user": user_obj.id, "right": right_obj.id})
                    right_ser.is_valid(raise_exception=True)
                    right_ser.save()
            except Exception as e:
                return Response({"ret": 1, "errors": str(e)})
            return Response({"ret": 0, 'msg': "ok"})
        else:
            return Response({"ret": 1, "errors": serializer.errors})


class GetRegisterCode(APIView):
    def post(self, request):
        serializer = MobileSerializer(data=request.data)
        if serializer.is_valid():
            print(current_thread())
            code = random.randrange(1000, 9999)
            print(f"{code=}")
            conn = get_redis_connection('default')
            conn.set(request.data['mobile'], code, ex=60)
            return Response({"ret": 0, "code": code})
        else:
            return Response({"ret": 1, "errors": serializer.errors})


class LoginApiView(APIView):
    def post(self, request):
        pwd = request.data.get("password")
        serializer = LoginSerializer(data=request.data, context={'session': request.session})
        if serializer.is_valid():
            user = serializer.validated_data.get('user')
            auth_user = authenticate(username=user.username, password=pwd)
            if auth_user:
                login(request, user)
                request.session.set_expiry(60 * 60 * 24 * 7)
                return Response({"ret": 0, "msg": '登录成功'})
            else:
                return Response({"ret": 1, "errors": {"password": ["密码错误！"]}})
        else:
            return Response({"ret": 1, "errors": serializer.errors})

    def get(self, request):
        logout(request)
        return redirect('main:index')


class PaymentApiView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        data = request.data.dict()
        if data.get("order_num"):
            instance = models.RightOrder.objects.filter(order_num=data.get("order_num"), order_status=1).first()
            if instance:
                if not self.check_history_order(instance):
                    return Response({"ret": 1, "errors": "由于权益价格已更新，当前订单已关闭，请重新下单"})
            else:
                return Response({"ret": 1, "errors": "订单不存在或者状态异常！"})
        else:
            data['order_status'] = 1
            data['order_num'] = uid(request.user.mobile)
            serializer = PaymentSerializer(data=data)
            if serializer.is_valid():
                instance = serializer.save()
            else:
                return Response({"ret": 1, "errors": serializer.errors})
        alipay_obj = AliPay(
            appid=settings.ALI_APPID,
            app_notify_url=settings.ALI_NOTIFY_URL,
            app_private_key_path=settings.ALI_PRI_KEY_PATH,
            alipay_public_key_path=settings.ALI_PUB_KEY_PATH,
            return_url=settings.ALI_RETURN_URL
        )
        pay_params = alipay_obj.direct_pay(
            subject=instance.order_right.title,
            out_trade_no=instance.order_num,
            total_amount=int(instance.order_price),
        )
        pay_url = f"{settings.ALI_GATEWAY}?{pay_params}"
        # return redirect(pay_url)
        return Response({"ret": 0, "payurl": pay_url})

    def check_history_order(self, instance):
        if instance.order_right and (instance.order_right.price * instance.order_quantity == instance.order_price):
            return True
        instance.order_status = 3
        instance.save()
        return False


class PaymentResultApiView(APIView):
    # 这个是支付宝支付成功后回调的请求视图

    def get(self, request):
        # 这个请求是用作页面跳转的，即ALI_RETURN_URL
        data = request.query_params.dict()
        # 检验请求是否是支付宝发出，并进行订单更新
        alipay_obj = AliPay(
            appid=settings.ALI_APPID,
            app_notify_url=settings.ALI_NOTIFY_URL,
            app_private_key_path=settings.ALI_PRI_KEY_PATH,
            alipay_public_key_path=settings.ALI_PUB_KEY_PATH,
            return_url=settings.ALI_RETURN_URL
        )
        sign = data.pop('sign', None)
        if alipay_obj.verify(data, sign):
            # 说明验签通过，请求正确
            with transaction.atomic():
                try:
                    instance = models.RightOrder.objects.filter(order_num=data.get('out_trade_no')).first()
                    instance.order_status = 2
                    user_right_obj = models.UserRight.objects.filter(user=request.user,
                                                                     right=instance.order_right).first()
                    if user_right_obj:
                        if user_right_obj.end_time > datetime.datetime.now():
                            user_right_obj.end_time += datetime.timedelta(days=365 * instance.order_quantity)
                        else:
                            user_right_obj.end_time = datetime.datetime.now() + datetime.timedelta(
                                days=365 * instance.order_quantity)
                        user_right_obj.save()
                    else:
                        models.UserRight.objects.create(
                            user=request.user,
                            right=instance.order_right,
                            end_time=datetime.datetime.now() + datetime.timedelta(days=365 * instance.order_quantity)
                        )
                    instance.save()
                except Exception as e:
                    return Response({"ret": 1, "errors": str(e)})
            return redirect('main:orderlist')
        else:
            return Response({"ret": 1, "errors": "非法请求"})

    def post(self, request):
        # 这个请求是支付宝的通知请求，即ALI_NOTIFY_URL
        # 如果有公网ip的话，所有接口逻辑应写在这里，目前暂时写在get中
        print(request.data)
